package lode

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
)

//得到一个文件的哈希值
func getSha256(filePath string) (string, error) {
	var hashValue string
	file, err := os.Open(filePath)
	if err != nil {
		return hashValue, err
	}
	defer file.Close()
	hash := sha256.New()
	if _, err := io.Copy(hash, file); err != nil {
		return hashValue, err
	}
	hashInBytes := hash.Sum(nil)
	hashValue = hex.EncodeToString(hashInBytes)
	return hashValue, nil
}

func getBytesSha256(bytes []byte) string {
	hash := sha256.New()
	hash.Write(bytes)
	return hex.EncodeToString(hash.Sum(nil))
}

//得到文件大小
func getSize(path string) int64 {
	if info, err := os.Stat(path); err != nil {
		return 0
	} else {
		return info.Size()
	}
}

func exists(filePath string) bool {
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return false
	}

	return true
}

func CreateIfNotExists(dir string, perm os.FileMode) error {
	if exists(dir) {
		return nil
	}
	if err := os.MkdirAll(dir, perm); err != nil {
		return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error())
	}
	return nil
}

func syncMapToImageMap(syncMap sync.Map) (normalMap map[string]*imageInfoEntry) {
	normalMap = make(map[string]*imageInfoEntry)
	syncMap.Range(func(key, value interface{}) bool {
		normalMap[key.(string)] = value.(*imageInfoEntry)
		return true
	})
	return
}

func imageMapToSyncMap(normalMap map[string]*imageInfoEntry) (syncMap sync.Map) {
	for key, value := range normalMap {
		syncMap.Store(key, value)
	}
	return
}

func layerMapToSyncMap(normalMap map[string]*layerInfoEntry) (syncMap sync.Map) {
	for key, value := range normalMap {
		syncMap.Store(key, value)
	}
	return
}

func syncMapToLayerMap(syncMap sync.Map) (normalMap map[string]*layerInfoEntry) {
	normalMap = make(map[string]*layerInfoEntry)
	syncMap.Range(func(key, value interface{}) bool {
		normalMap[key.(string)] = value.(*layerInfoEntry)
		return true
	})
	return
}

func trimDigestPrefix(digest, prefix string) string {
	return strings.TrimPrefix(digest, prefix)
}

func getTarFileSuffixAndType(mediaType string) (string, string) {
	t := strings.Split(mediaType, ".")
	s := t[len(t)-1]

	switch s {
	case "gzip":
		return "tar.gz", "gzip"
	case "zstd":
		return "tar.zst", "zstd"
	default:
		return "tar", "tar"
	}
}
